use std::sync::Arc;
use std::time::Duration;
use nacos_rust_client::client::naming_client::{NamingClient, QueryInstanceListParams};
use nacos_rust_client::client::{AuthInfo, ClientBuilder};

// 导入 infra 服务的客户端
use infra_dict::dict_client::DictClient;
use infra_dict::{GetDataListReq as DictReq, GetDataListRes as DictRes};
use infra_notice::notice_client::NoticeClient;
use infra_notice::{SendNoticeReq as NoticeReq, SendNoticeRes as NoticeRes};

pub mod infra_dict {
    tonic::include_proto!("dict");
}

pub mod infra_notice {
    tonic::include_proto!("notice");
}

struct InfraClient {
    naming_client: Arc<NamingClient>,
}

impl InfraClient {
    async fn new() -> Result<Self, Box<dyn std::error::Error>> {
        let namespace_id = "public".to_owned();
        let auth_info: Option<AuthInfo> = None;
        
        let client = ClientBuilder::new()
            .set_endpoint_addrs("152.136.130.146:8848")
            .set_auth_info(auth_info)
            .set_tenant(namespace_id)
            .set_use_grpc(true)
            .set_app_name("infra-client".to_owned())
            .build_naming_client();

        Ok(Self {
            naming_client: client,
        })
    }

    async fn get_service_endpoint(&self, service_name: &str) -> Result<String, Box<dyn std::error::Error>> {
        let params = QueryInstanceListParams::new_simple(service_name, "DEFAULT_GROUP");
        match self.naming_client.select_instance(params).await {
            Ok(instance) => {
                let endpoint = format!("http://{}:{}", instance.ip, instance.port);
                println!("获取到 {} 服务地址: {}", service_name, endpoint);
                Ok(endpoint)
            }
            Err(e) => {
                eprintln!("获取 {} 服务实例失败: {:?}", service_name, e);
                Err(format!("服务发现失败: {}", e).into())
            }
        }
    }

    async fn test_dict_service(&self) -> Result<(), Box<dyn std::error::Error>> {
        println!("\n=== 测试 Dict 服务 ===");
        let endpoint = self.get_service_endpoint("infra-dict").await?;
        let mut client = DictClient::connect(endpoint).await?;

        let request = tonic::Request::new(DictReq {
            name: "测试字典".to_string(),
        });

        let response = client.get_data_list(request).await?;
        println!("Dict 服务响应: {}", response.into_inner().message);
        Ok(())
    }

    async fn test_notice_service(&self) -> Result<(), Box<dyn std::error::Error>> {
        println!("\n=== 测试 Notice 服务 ===");
        let endpoint = self.get_service_endpoint("infra-notice").await?;
        let mut client = NoticeClient::connect(endpoint).await?;

        let request = tonic::Request::new(NoticeReq {
            title: "测试通知".to_string(),
            content: "这是一条来自 infra 客户端的测试通知".to_string(),
        });

        let response = client.send_notice(request).await?;
        println!("Notice 服务响应: {}", response.into_inner().message);
        Ok(())
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    unsafe { std::env::set_var("RUST_LOG", "INFO"); }
    env_logger::init();

    println!("Infra Client 启动，等待服务发现...");
    
    // 等待服务启动
    tokio::time::sleep(Duration::from_secs(3)).await;

    let infra_client = InfraClient::new().await?;

    loop {
        println!("\n========== Infra 服务测试 ==========");
        
        // 测试字典服务
        if let Err(e) = infra_client.test_dict_service().await {
            eprintln!("测试字典服务失败: {}", e);
        }

        // 测试通知服务
        if let Err(e) = infra_client.test_notice_service().await {
            eprintln!("测试通知服务失败: {}", e);
        }

        println!("\n等待 5 秒后继续下一轮测试...");
        tokio::time::sleep(Duration::from_secs(5)).await;
    }
}
